//
// Created by fairy on 2025/4/26 22:47.
//
#ifndef KEY_HPP
#define KEY_HPP
#include<zq_drivers.h>
#include <stdint.h>

namespace bsp
{
    namespace key
    {
        namespace detail
        {
            DECLARE_MEMORY_REGION(KEY, 0x602800);

            DECLARE_MEMORY_REGION(KEY_CTRL, 0x600801);
        }
    }
}


namespace bsp
{
    class Key
    {
    public:
        DECLARE_ATTRIBUTE(Event,
                          NONE = 0x00,
                          SHORT_PRESS = 0x01,
                          LONG_PRESS // 硬件上不支持，软件上自然无法实现
        )

    private:
        DECLARE_ATTRIBUTE(State,
                          IDLE,
                          PRESS_DEBOUNCE,
                          PRESSED,
                          RELEASE_DEBOUNCE
        )

        DECLARE_ATTRIBUTE(Time,
                          DEBOUNCE_TIME = 200,
                          LONG_PRESS_THRESHOLD = 800
        )


        static volatile State::Type m_state;
        static volatile uint32_t m_last_edge_time;
        static volatile Event::Type m_pending_event;
        static volatile uint16_t m_key_code;

    public:
        static void init()
        {
            // 硬件初始化
            zq::cpu::IER0::INT2::set();
            zq::cpu::DBIER0::INT2::set();
            zq::cpu::IFR0::INT2::set();

            key::detail::KEY_CTRL::write(0xC8);
            m_last_edge_time = key::detail::KEY_CTRL::read();

            // 状态初始化
            m_state = State::IDLE;
            m_pending_event = Event::NONE;
            m_key_code = 0;
        }

        static void handleInterrupt()
        {
            // 读取键值并消抖
            uint16_t temp_key = 0;
            for (uint16_t i = 0; i < 5; ++i)
            {
                temp_key = key::detail::KEY::read();
                if (temp_key != 0) break;
                zq::systick::Delay::us(10);
            }
            // 清零寄存器
            m_last_edge_time = key::detail::KEY_CTRL::read();

            // 更新键值和边沿时间
            m_key_code = temp_key;
            m_last_edge_time = zq::systick::get_tick();
            // zq::systick::Delay::us(1500);

            // 状态转移
            if (m_key_code != 0)
            {
                if (m_state == State::IDLE)
                {
                    m_state = State::PRESS_DEBOUNCE;
                }
            }
        }

        static void poll()
        {
            const uint32_t now = zq::systick::get_tick();
            const uint32_t delta = now - m_last_edge_time;
            switch (m_state)
            {
                case State::PRESS_DEBOUNCE:
                    // 首次直接进入按键状态
                    m_pending_event = Event::SHORT_PRESS;
                    m_state = State::PRESSED;
                    break;

                case State::PRESSED:
                    // 防抖
                    if (delta > Time::DEBOUNCE_TIME)
                    {
                        m_state = State::IDLE;
                    }
                    break;
                default:
                    break;
            }
        }

        static Event::Type getEvent()
        {
            const Event::Type ret = m_pending_event;
            m_pending_event = Event::NONE;
            return ret;
        }

        static uint16_t getCode() { return m_key_code; }
    };
}


#endif //KEY_HPP
